package cn.org.xuanguang.kepler.hormos.rdb.plugin.mysql;

import cn.org.xuanguang.kepler.exception.ExceptionLevel;
import cn.org.xuanguang.kepler.exception.KeplerRuntimeException;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.sql.PrepareSqlFragments;
import cn.org.xuanguang.kepler.hormos.rdb.expection.EntityNullException;
import cn.org.xuanguang.kepler.hormos.rdb.plugin.DdlSQLBuilder;
import cn.org.xuanguang.kepler.metadata.relational.KeplerMetaColumn;
import cn.org.xuanguang.kepler.metadata.relational.KeplerMetaTable;

import java.sql.JDBCType;

public class MysqlDdlSQLBuilder implements DdlSQLBuilder {
    @Override
    public String getCreateDatabaseDDL(String databaseName) {
        if (databaseName != null) {
            return "CREATE DATABASE IF NOT EXISTS " + databaseName;
        }
        return "";
    }

    @Override
    public String getCreateDatabaseDDL(String databaseName, String charset) {
        if (databaseName != null) {
            return "CREATE DATABASE IF NOT EXISTS " + databaseName + " DEFAULT CHARSET " + charset;
        }
        return "";
    }

    @Override
    public String getDropDatabaseDDL(String databaseName) {
        if (databaseName != null) {
            return "DROP DATABASE IF EXISTS " + databaseName;
        }
        return "";
    }

    @Override
    public String getCreateTableDDL(String databaseName, String tableName) {
        if (databaseName != null && tableName != null) {
            return "CREATE TABLE IF NOT EXISTS " + databaseName + "." + tableName;
        }
        return "";
    }

    /**
     * CREATE TABLE `x_tabular` (
     *   `KEY` varchar(36) NOT NULL COMMENT '「key」- 列表主键',
     *   `NAME` varchar(255) DEFAULT NULL COMMENT '「name」- 列表名称',
     *   `CODE` varchar(255) DEFAULT NULL COMMENT '「code」- 列表编号',
     *   `TYPE` varchar(255) DEFAULT NULL COMMENT '「type」- 列表类型',
     *   `ICON` varchar(255) DEFAULT NULL COMMENT '「icon」- 列表图标',
     *   `SORT` int(11) DEFAULT NULL COMMENT '「sort」- 排序信息',
     *   `COMMENT` text COMMENT '「comment」- 备注信息',
     *   `APP_ID` varchar(255) DEFAULT NULL COMMENT '「appId」- 关联的应用程序ID',
     *   `ACTIVE` bit(1) DEFAULT NULL COMMENT '「active」- 是否启用',
     *   `SIGMA` varchar(32) DEFAULT NULL COMMENT '「sigma」- 统一标识',
     *   `METADATA` text COMMENT '「metadata」- 附加配置',
     *   `LANGUAGE` varchar(8) DEFAULT NULL COMMENT '「language」- 使用的语言',
     *   `CREATED_AT` datetime DEFAULT NULL COMMENT '「createdAt」- 创建时间',
     *   `CREATED_BY` varchar(36) DEFAULT NULL COMMENT '「createdBy」- 创建人',
     *   `UPDATED_AT` datetime DEFAULT NULL COMMENT '「updatedAt」- 更新时间',
     *   `UPDATED_BY` varchar(36) DEFAULT NULL COMMENT '「updatedBy」- 更新人',
     *   PRIMARY KEY (`KEY`),
     *   UNIQUE KEY `APP_ID` (`APP_ID`,`TYPE`,`CODE`),
     *   UNIQUE KEY `SIGMA` (`SIGMA`,`TYPE`,`CODE`),
     *   KEY `IDXM_X_TABULAR_APP_ID_TYPE_ACTIVE` (`APP_ID`,`TYPE`,`ACTIVE`),
     *   KEY `IDXM_X_TABULAR_SIGMA_TYPE_ACTIVE` (`SIGMA`,`TYPE`,`ACTIVE`)
     * ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
     * @param keplerMetaTable
     * @return
     */
    @Override
    public String getCreateTableDDL(KeplerMetaTable keplerMetaTable) {
        PrepareSqlFragments sql = PrepareSqlFragments.of();

        // 创建表
        if (keplerMetaTable != null) {
            if (keplerMetaTable.getCatalogName() != null && !"".equals(keplerMetaTable.getCatalogName())){
                sql.addSql("CREATE TABLE IF NOT EXISTS " + keplerMetaTable.getCatalogName() + "." + keplerMetaTable.getTableName());
            }else if (keplerMetaTable.getSchemaName() != null && !"".equals(keplerMetaTable.getSchemaName())){
                sql.addSql( "CREATE TABLE IF NOT EXISTS " + keplerMetaTable.getSchemaName() + "." + keplerMetaTable.getTableName());
            }else if (keplerMetaTable.getTableName() != null){
                sql.addSql("CREATE TABLE IF NOT EXISTS " + keplerMetaTable.getTableName());
            }
            //表字段
            sql.addSql("(");
            for (int i = 0; i < keplerMetaTable.getColumns().size(); i++) {
                sql.addSql(keplerMetaTable.getColumns().get(i).getColumnName());
                //字段类型转成对应的数据库类型
//                抽取公共方法，实现数据类型转mysql的类型
                sql.addSql(getDbDataType(keplerMetaTable.getColumns().get(i)));
                //主键
                if (keplerMetaTable.getColumns().get(i).isPrimaryKey()) {
                    sql.addSql(" PRIMARY KEY");
                }
                // 是否自增
                if (keplerMetaTable.getColumns().get(i).isAutoIncrement()) {
                    sql.addSql(" AUTO_INCREMENT");
                }
                // 判断是否允许为空
                    if (keplerMetaTable.getColumns().get(i).isNullable()) {
//                        sql.addSql(" NULL");
                    } else {
                        sql.addSql(" NOT NULL");
                    }
                    if (keplerMetaTable.getColumns().get(i).getDefaultValue() != null && !"".equals(keplerMetaTable.getColumns().get(i).getDefaultValue())) {
                       //加引号
                        sql.addSql(" DEFAULT '" + keplerMetaTable.getColumns().get(i).getDefaultValue() + "'");
                    }
                    if (keplerMetaTable.getColumns().get(i).getComment() != null) {
                        sql.addSql(" COMMENT '" + keplerMetaTable.getColumns().get(i).getComment() + "'");
                    }
                    //其他约束

                    // 判断是否为最后一个字段
                    if (i < keplerMetaTable.getColumns().size() - 1) {
                        sql.addSql(",");
                    }
            }
//            // PRIMARY KEY (`KEY`), 约束
//            if (keplerMetaTable.getPrimaryKeys() != null) {
//                sql.addSql(",");
//                // 输出为字符串，用，隔开
//                sql.addSql("PRIMARY KEY (" + keplerMetaTable.getPrimaryKeys().stream().toArray(String[]::new) + ")");
//                sql.addSql(",");
//                sql.addSql("UNIQUE KEY (" + keplerMetaTable.getPrimaryKeys().stream().toArray(String[]::new) + ")");
//            }
//
            sql.addSql(")");
            // 添加引擎约束
            sql.addSql("ENGINE=InnoDB DEFAULT CHARSET=utf8;");
//            //添加表级别约束
//            if (keplerMetaTable.getConstraints() != null) {
//                for (int i = 0; i < keplerMetaTable.getTableConstraints().size(); i++) {
//                    sql.addSql(keplerMetaTable.getTableConstraints().get(i).getConstraintName());
//                    sql.addSql(keplerMetaTable.getTableConstraints().get(i).getConstraintType());
//                    sql.addSql(keplerMetaTable.getTableConstraints().get(i).getConstraintColumns());
//                   // 判断是否为最后一个字段
//               }
//           }

        }


        return sql.toRequest().getSql();
    }

    /**
     * 注解类型转成数据库数据类型
     * @param keplerMetaColumn
     * @return
     */
    @Override
    public String getDbDataType(KeplerMetaColumn keplerMetaColumn) {
        if (keplerMetaColumn.getJdbcType() == JDBCType.VARCHAR) {
            return "VARCHAR(" + keplerMetaColumn.getColumnLength() + ")";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.CHAR) {
            return "CHAR(" + keplerMetaColumn.getColumnLength() + ")";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.LONGVARCHAR) {
            return "TEXT";
        }
//        INTEGER
        if (keplerMetaColumn.getJdbcType() == JDBCType.INTEGER) {
            return "INTEGER";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.BIGINT) {
            return "BIGINT";
        }
//       DATE
        if (keplerMetaColumn.getJdbcType() == JDBCType.DATE) {
            return "DATE";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.TIMESTAMP) {
            return "TIMESTAMP";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.TIME) {
            return "TIME";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.BOOLEAN) {
            return "BOOLEAN";
        }
//        decimal
        if (keplerMetaColumn.getJdbcType() == JDBCType.DECIMAL) {
            return "DECIMAL(" + keplerMetaColumn.getPrecision() + "," + keplerMetaColumn.getScale() + ")";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.NUMERIC) {
            return "NUMERIC(" + keplerMetaColumn.getColumnLength() + "," + keplerMetaColumn.getScale() + ")";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.REAL) {
            return "REAL";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.DOUBLE) {
            return "DOUBLE";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.FLOAT) {
            return "FLOAT";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.BIT) {
            return "BIT";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.TINYINT) {
            return "TINYINT";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.SMALLINT) {
            return "SMALLINT";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.BINARY) {
            return "BINARY";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.VARBINARY) {
            return "VARBINARY";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.LONGVARBINARY) {
            return "LONGVARBINARY";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.BLOB) {
            return "BLOB";
        }
        if (keplerMetaColumn.getJdbcType() == JDBCType.CLOB) {
            return "CLOB";
        }



        return "";
    }

    @Override
    public String getDropTableDDL(KeplerMetaTable keplerMetaTable) {
        if (keplerMetaTable != null) {
            if (keplerMetaTable.getCatalogName() != null && !"".equals(keplerMetaTable.getCatalogName())){
                return "DROP TABLE IF EXISTS " + keplerMetaTable.getCatalogName() + "." + keplerMetaTable.getTableName();
            }
            if (keplerMetaTable.getSchemaName() != null && !"".equals(keplerMetaTable.getSchemaName())){
                return "DROP TABLE IF EXISTS " + keplerMetaTable.getSchemaName() + "." + keplerMetaTable.getTableName();
            }
            return "DROP TABLE IF EXISTS " + keplerMetaTable.getTableName();
        }else {
            throw new EntityNullException("keplerMetaTable is null") ;
        }
    }

    @Override
    public String getAlterTableDDL(KeplerMetaTable keplerMetaTable) {
        if (keplerMetaTable != null) {
            if (keplerMetaTable.getCatalogName() != null){
                return "ALTER TABLE " + keplerMetaTable.getCatalogName() + "." + keplerMetaTable.getTableName();
            }
            if (keplerMetaTable.getSchemaName() != null){
                return "ALTER TABLE " + keplerMetaTable.getSchemaName() + "." + keplerMetaTable.getTableName();
            }
        }
        return "";
    }

    @Override
    public String getCreateIndexDDL(KeplerMetaTable keplerMetaTable) {
        if (keplerMetaTable != null  && !"".equals(keplerMetaTable.getCatalogName())) {
            if (keplerMetaTable.getCatalogName() != null){
                return "CREATE INDEX " + keplerMetaTable.getCatalogName() + "." + keplerMetaTable.getTableName();
            }
            if (keplerMetaTable.getSchemaName() != null && !"".equals(keplerMetaTable.getSchemaName())){
                return "CREATE INDEX " + keplerMetaTable.getSchemaName() + "." + keplerMetaTable.getTableName();
            }
        }else{
            throw new EntityNullException("keplerMetaTable is null") ;
        }
        return "";
    }

    @Override
    public String getDropIndexDDL(KeplerMetaTable keplerMetaTable) {
        if (keplerMetaTable != null) {
            if (keplerMetaTable.getCatalogName() != null && !"".equals(keplerMetaTable.getCatalogName())){
                return "DROP INDEX " + keplerMetaTable.getCatalogName() + "." + keplerMetaTable.getTableName();
            }
            if (keplerMetaTable.getSchemaName() != null && !"".equals(keplerMetaTable.getSchemaName())){
                return "DROP INDEX " + keplerMetaTable.getSchemaName() + "." + keplerMetaTable.getTableName();
            }
            return "DROP INDEX " + keplerMetaTable.getTableName();
        }else
            throw new EntityNullException("keplerMetaTable is null") ;
    }

    @Override
    public String getRenameTableDDL(String databaseName, String oldTableName, String newTableName) {
       // 判断空
        if (oldTableName == null || "".equals(oldTableName)){
            throw new EntityNullException("oldTableName is null") ;
        }
        // 修改表名
        if (databaseName != null && !"".equals(databaseName)){
            return "ALTER TABLE " + databaseName + "." + oldTableName + " RENAME TO " + newTableName;
        }
        return "ALTER TABLE " + oldTableName + " RENAME TO " + newTableName;
    }
}
